home *** CD-ROM | disk | FTP | other *** search
- ##############################################################################
- # HTTP Cookie Library Version 2.1 #
- # Copyright 1996 Matt Wright mattw@worldwidemart.com #
- # Created 07/13/96 Last Modified 12/23/96 #
- # Scripts Archive at: http://www.worldwidemart.com/scripts/ #
- # Parts of Code Contributed by Jeff Carnahan (http://terminalp.com/scripts/) #
- ##############################################################################
- # If you run into any problems while trying to configure this script, help #
- # is available. The steps you should take to get the fastest results, are: #
- # 1) Read this file thoroughly #
- # 2) Consult the Matt's Script Archive Frequently Asked Questions: #
- # http://www.worldwidemart.com/scripts/faq/ #
- # 3) If you are still having difficulty installing this script, send #
- # e-mail to: scripts-help@tahoenet.com #
- # Include any error messages you are receiving and as much detail #
- # as you can so we can spot your problem. Also include the variable#
- # configuration block that is located at the top of the script. #
- # #
- # Hopefully we will be able to help you solve your problems. Thank you. #
- ##############################################################################
- # COPYRIGHT NOTICE #
- # Copyright 1996 Matthew M. Wright All Rights Reserved. #
- # #
- # HTTP Cookie Library may be used and modified free of charge by anyone so #
- # long as this copyright notice and the comments above remain intact. By #
- # using this code you agree to indemnify Matthew M. Wright from any #
- # liability that might arise from it's use. #
- # #
- # Selling the code for this program without prior written consent is #
- # expressly forbidden. In other words, please ask first before you try and #
- # make money off of my program. #
- # #
- # Obtain permission before redistributing this software over the Internet or #
- # in any other medium. In all cases copyright and header must remain intact #
- ##############################################################################
-
- TABLE OF CONTENTS:
- ==================
-
- 1) Overview
- 2) cookie.lib Configuration
- a) $Cookie_Exp_Date
- b) $Cookie_Path
- c) $Cookie_Domain
- d) $Secure_Cookie
- e) @Cookie_Encode_Chars
- f) %Cookie_Encode_Chars
- g) @Cookie_Decode_Chars
- h) %Cookie_Decode_Chars
- 3) Using this Library in your CGI script.
- a) Requiring the library.
- b) Subroutine calls.
- + &GetCookies
- + &SetCookieExpDate
- + &SetCookiePath
- + &SetCookieDomain
- + &SetSecureCookie
- + &SetCookies
- + &SetCompressedCookies
- + &GetCompressedCookies
- 4) Character Translation Information
- 5) Any Examples Available?
- a) ccounter.pl
- b) Scripts Around the World
- 6) Other Cookie Resources
- 7) History
-
- ##############################################################################
-
- OVERVIEW
- ========
-
- HTTP Cookie Library is a Perl 4 and 5 compatible library which allows you to
- easily use Persistent Client State HTTP Cookies by allowing you to get the
- cookies from the environment, prepare cookies, set cookies, change the
- expiration date, domain and path all with easy subroutine calls.
-
- Version 2.0 and 2.1 contain many changes, including the ability to compress
- multiple cookies into one, the elimination of the &PrepareCookies subroutine,
- and fixes allowing you to set more than one cookie at a time. The addition of
- character URL-encoding and the fixing of a scoping bug brought on by
- localizing the global variables used in this script are new to version 2.1.
-
- NOTE: Anyone who used 2.0 and &UnCompressCookies should now change all
- references from &UnCompressCookies to &GetCompressedCookies. The calls
- to these routines are the same, however the name has been changed.
-
- For more information on Cookies, and to see the preliminary specifications
- of Persistent Client State HTTP Cookies to which this library conforms, visit
- http://www.netscape.com/newsref/std/cookie_spec.html
-
- There are three files included with this script:
- 1) README - This file; includes detailed installation
- instructions.
- 2) cookie.lib - The Perl script which generates the random phrase
- and displays it on your web page.
- 3) ccounter.pl - An example of how to use this library.
-
- The cookie.lib perl library is not a stand-alone CGI script. It is meant to
- be used in conjunction with a script that you build. It's only purpose is to
- facilitate the usage of client side persistent HTTP cookies. This means, in
- order to use this library, you should always have the following line in your
- script somewhere:
-
- require '/path/to/cookie.lib';
-
- This will then tell Perl to retrieve this file and include it's code and
- subroutines in your script. Nonetheless, there are some variables which you
- can modify in the cookie.lib file before you place it on your system. All
- of these variables can be modified through special subroutines in cookie.lib
- so it is not necessary to edit any of them.
-
- ##############################################################################
-
- COOKIE.LIB CONFIGURATION
- ========================
-
- This program contains three variables which can be modified in the library, to
- make it easier to use on your system. They can also be set through calling
- subroutines, which is explained in: 'Using this Library in Your CGI Script,'
- or by setting them in your main script, as they are local variables which can
- be modified. The subroutines provide checks to make sure the value is valid.
-
- $Cookie_Exp_Date = '';
- This variable defines the expiration date of your cookie.
- When this date arrives the browser will ask the user if
- they want to delete the cookie, and that it is ok to do so.
- This date must always be represented as:
- Wdy, DD-Mon-YYYY HH:MM:SS GMT
- and always has to be in GMT time. An example would be:
- Wed, 09-Nov-1999 00:00:00 GMT. By default, if this is
- not filled in, the browser will delete the cookie when the
- session ends. Also see &SetCookieExpDate.
-
- $Cookie_Path = '';
- This path defines where under your domain the cookies
- should be sent. For instance, if your URL is:
- http://domain.xxx/your_dir/, there is no reason for the
- browser to send the Cookie header to the base domain name.
- Therefore, you would set this to '/your_dir'; However,
- because this can be set through the script, set it to
- whatever directory will use this most often or whichever
- directory you want as default. If nothing is placed here,
- the default will be assumed to be the script or page which
- created the cookie. Also see &SetCookiePath.
-
- $Cookie_Domain = '';
- This defines the base domain to which the browse passes the
- cookie. If you have a domain: www.host.xxx, your.host.xxx
- and host.xxx, which all will use this, you would set this
- variable to: '.host.xxx'; The following is an excerpt from
- the Netscape Preliminary Specifications of Persistent Client
- State HTTP Cookies:
-
- "Only hosts within the specified domain can set a cookie for
- a domain and domains must have at least two (2) or three (3)
- periods in them to prevent domains of the form: ".com",
- ".edu", and "va.us". Any domain that fails within one of the
- seven special top level domains listed below only require
- two periods. Any other domain requires at least three. The
- seven special top level domains are: "COM", "EDU", "NET",
- "ORG", "GOV", "MIL", and "INT"."
-
- Also see &SetCookieDomain.
-
- $Secure_Cookie = '0';
- This defines whether or not you want to restrict the
- transmission of the cookie to a secure server. If this flag
- is set to '1', by default the cookies you create will only be
- sent to secure servers by the client. This can also be
- changed through &SetSecureCookie.
-
- @Cookie_Encode_Chars = ('\%', '\+', '\;', '\,', '\=', '\&', '\:\:', '\s');
- This defines the order in which the special characters should
- be encoded. More info can be found in section entitled
- 'Character Translation Information'.
-
- %Cookie_Encode_Chars = ('\%', '%25',
- '\+', '%2B',
- '\;', '%3B',
- '\,', '%2C',
- '\=', '%3D',
- '\&', '%26',
- '\:\:', '%3A%3A',
- '\s', '+');
- This associative array defines the characters to be
- translated as the keys, which can be referred to as:
- $Cookie_Encode_Chars{key} and the values which these
- characters should be translated into. More info can
- be found in section entitled 'Character Translation
- Information'.
-
- @Cookie_Decode_Chars = ('\+', '\%3A\%3A', '\%26', '\%3D', '\%2C', '\%3B', '\%2B', '\%25');
- This defines the order in which the special characters should
- be decoded. More info can be found in section entitled
- 'Character Translation Information'.
-
- %Cookie_Decode_Chars = ('\+', ' ',
- '\%3A\%3A', '::',
- '\%26', '&',
- '\%3D', '=',
- '\%2C', ',',
- '\%3B', ';',
- '\%2B', '+',
- '\%25', '%');
- This associative array defines the characters to be
- translated as the keys, which can be referred to as:
- $Cookie_Decode_Chars{key} and the values which these
- characters should be decoded into. More info can be
- found in section entitled 'Character Translation
- Information'.
-
-
- ##############################################################################
-
- USING THIS LIBRARY IN YOUR CGI SCRIPT.
- ======================================
-
- HTTP Cookie Library is not meant as a standalone CGI script. It must be used
- in conjunction with other scripts you have written, and provides a basic
- outline and easy subroutines which makes implementing the cookies into your
- perl program easy.
-
- Also, to give cookies to the user, the browser must be pointed to the CGI
- application or the CGI application must be imbedded in the HTML document
- through Server Side Includes or other technology, such as JavaScript. If
- you choose the JavaScript path, some browsers which support cookies won't
- be able to receive them and JavaScript users have no use for this library
- as it is only compatible in Perl scripted CGI applications.
-
- Requiring the Library:
- ----------------------
-
- Near the top of your Perl CGI script (or before you make the first call to a
- subroutine which is in cookie.lib), you will need to include the line:
-
- require '/path/to/cookie.lib';
-
- If you place the cookie.lib in the same directory as your CGI script, or in
- a path which is defined in @INC, you can call it with:
-
- require 'cookie.lib';
-
- Now all of the subroutines which this script contains can be used in your CGI
- Perl script. Here's is a summary of them, what they do and how to call them:
-
- Subroutine Calls:
- -----------------
-
- &GetCookies('cookie_name1',...,'cookie_namen');
- This function can be called as simply &GetCookies, or using arguments
- such as &GetCookies('cookie1','cookie2'). Calling it without
- arguments means that it will return a '1' if cookies are found, a 0
- if they are not. This is useful, so that you can perform function
- like:
-
- if (&GetCookies) {
- # Successful Code Here;
- }
- else {
- # Give them a Cookie Here;
- }
-
- In the above circumstance, if cookies are found, the successful code
- gets executed. Otherwise, you can give them a cookie. The
- &GetCookies subroutine then takes the cookies from the environment
- and places them in an associative array. This array is %Cookies.
- So if you have set a cookie named 'visit' with a value which contains
- whatever you set it for, then you would obtain this value by using
- the scalar variable $Cookies{'visit'}.
-
- Now, let's say that a lot of cookies are set for your base domain and
- path. They would all get included in the return if you didn't
- specify arguments for &GetCookies. For instance, in the above
- example, since &GetCookies would return a value of '1' if any cookies
- are set, that could mess up this script, if all we want to know is if
- the visit cookie is set. Therefore, we would change the above program
- to only need to 'visit' cookie:
-
- if (&GetCookies('visit')) {
- # Successful Code Here;
- }
- else {
- # Give them a Cookie Here;
- }
-
- Now, only the $Cookies{'visit'} scalar will be set and if it is not
- &GetCookies will return a 0 and the else { } statement will be
- executed.
-
- You can check for multiple cookies to be set by &GetCookies('name1',
- 'name2','etc...'); However this will return a true value (1) if any
- of those cookies are set. You can get around this by calling them one
- at a time, although this is tedious.
-
- If you have compressed your cookies with &SetCompressedCookies, you
- will need to look into the &GetCompressedCookies routine to do what
- &GetCookies does.
-
- &SetCookieExpDate('Wdy, DD-Mon-YYYY HH:MM:SS GMT');
-
- By default in the script, the cookie is set to expire when the browser
- session ends. If you wish for the cookie to expire at a later date,
- then all you have to do is change the date by calling &SetCookieExpDate
- with an argument containing the new date. The new date must be in the
- format as shown above, or it will not set right. The following is an
- example:
-
- &SetCookieExpDate('Wed, 09-Nov-1999 00:00:00 GMT');
-
- If your date does not match a regular expression which checks to see
- if it is valid, it will return a 0. So it you catch the value, you
- can do:
-
- if (&SetCookieExpDate('Wdy, DD-Mon-YYYY HH:MM:SS GMT')) {
- # Continue here.
- }
- else {
- # Do Error Stuff Here. &SetCookieExpDate failed.
- }
-
- For any cookies which you wish to be able to detect if the user closes
- the browser's session and then re-opens it, you will need to set this
- to a specific date.
-
- The $Cookie_Exp_Date variable can also be changed at the top of
- cookie.lib, or at any point inside of the perl script which required
- cookie.lib, simply with the statement:
- $Cookie_Exp_Date = 'Wdy, DD-Mon-YYYY HH:MM:SS GMT';
- The subroutine is provided to check the syntax of your date.
-
- &SetCookiePath('/path');
-
- By default, this is set to the path of the script or web page which sets
- the cookie, so unless this has been set differently in cookie.lib to
- contain a value, you need not call this function. However, if you wish
- for those values to be passed to other scripts under the same domain,
- you will need to have this set to that path of the URL. For
- instance, if I only want my cookies passed to URLs which are at least:
- http://www.worldwidemart.com/scripts, I would call this function as:
-
- &SetCookiePath('/scripts');
-
- You can also set the cookie path with the statement:
- $Cookie_Path = '/path/you/want/to/set';
- You can place this statement anywhere in your Perl programs after you
- have required the cookie.lib library.
-
- &SetCookieDomain('.host.xxx');
-
- If the value of your desired domain suffix (.host.xxx) was assigned
- a different value as default, you can change this by placing a domain
- name in the call to &SetCookieDomain. Most of the time you shouldn't
- have to worry about this. Below are the rules which this script
- follows, taken directly from Netscape documentation:
-
- "Only hosts within the specified domain can set a cookie for
- a domain and domains must have at least two (2) or three (3)
- periods in them to prevent domains of the form: ".com",
- ".edu", and "va.us". Any domain that fails within one of the
- seven special top level domains listed below only require
- two periods. Any other domain requires at least three. The
- seven special top level domains are: "COM", "EDU", "NET",
- "ORG", "GOV", "MIL", and "INT"."
-
- The $Cookie_Domain can also be set using the statemement:
- $Cookie_Domain = 'host.xxx';
- You can place this statement anywhere in your Perl programs after you
- have required the cookie.lib library.
-
- &SetSecureCookie('0' || '1');
-
- This defines whether or not this cookie should be relayed only to
- secure servers. Calling &SetSecureCookie('1'); means that clients
- will only pass those cookies you have set to secure servers.
- Calling &SetSecureCookie('0'); means the cookies will be transferred
- whenever the path and domain are correct, regardless of security issues.
- Here is an excerpt from Netscape specs:
-
- "If a cookie is marked secure, it will only be transmitted if the
- communications channel with the host is a secure one. Currently
- this means that secure cookies will only be sent to HTTPS (HTTP
- over SSL) servers. If secure is not specified, a cookie is
- considered safe to be sent in the clear over unsecured channels."
-
- You can also change the value of $Secure_Cookie through a statement:
- $Secure_Cookie = 1; or $Secure_Cookie = 0;
- You can place this statement anywhere in your Perl programs after you
- have required the cookie.lib library.
-
- &SetCookies('cookie_name1','cookie_value1',...,'cookie_namen','cookie_valuen');
- This function has been completely changed since Version 1.1.1, except
- for the fact that it actually does set the cookies. There is no longer
- a call to &PrepareCookies, but rather &SetCookies does it all.
-
- If you wish to set the cookies name and email, and have the values of
- these cookies in the variables $name and $email, you would set them with
- the following code:
-
- print "Content-type: text/html\n";
- &SetCookies('name',"$name",'email',"$email");
- print "\n";
-
- The first line prints out the text/html header, with one new line
- following it, rather than two, since the header sent to the browser is
- not yet complete. Then, our call to &SetCookies is made. This call
- will send two Set-Cookie: headers to the browser and set both of the
- cookies for us.
-
- You can send as many cookies to this subroutine as you wish to set.
- Browsers do have a limit though, so if you are setting multiple
- cookies, it is suggested that you look into the &SetCompressedCookies
- subroutine.
-
- &SetCompressedCookies('compressed_cookie_name','cookie_name1','cookie_value1',
- ...,'cookie_namen','cookie_valuen');
-
- This subroutine does almost the same thing that &SetCookies does, but
- instead it takes one extra argument. You call it with the name of the
- compressed cookie which you wish to set and then the name/value pairs of
- of the cookies which you wish to compress. This subroutine doesn't
- actually compress cookies, but it takes multiple cookies and strings
- them together, so to the browser they appear as one. The = signs are
- converted into :: and the name/value pairs are separated from each other
- by &, however there is no need to change these characters before hand,
- as they will be translated back when uncompressed.
-
- You may be saying, why should I bother compressing cookies when it takes
- extra work? I can just set 50 cookies all for different things. The
- main reason is, that according to Netscape's specification:
-
- "There are limitations on the number of cookies that a client can
- store at any one time. This is a specification of the minimum
- number of cookies that a client should be prepared to receive and
- store.
-
- -- 300 total cookies
- -- 4 kilobytes per cookie, where the name and the value combine
- to form the 4 kilobyte limit.
- -- 20 cookies per server or domain. (note that completely
- specified hosts and domains are treated as separate entities
- and have a 20 cookie limitation for each, not combined)
-
- Servers should not expect clients to be able to exceed these
- limits. When the 300 cookie limit or the 20 cookie per server
- limit is exceeded, clients should delete the least recently used
- cookie. When a cookie larger than 4 kilobytes is encountered the
- cookie should be trimmed to fit, but the name should remain intact
- as long as it is less than 4 kilobytes."
-
- This also means that it is up to you to check and make sure that your
- compressed cookie will not take more than 4KB. This is not going to be
- a common problem most likely, though, as 4KB is 4,000 characters, which
- if typed out on a common 80 column screen is about 50 lines, or almost
- a full page of text. The 20 cookie limit on one server name is
- definitely a common problem, and this helps save some of this space.
- As cookies become more common, clients may start reaching the 300
- cookie maximum more rapidly as well.
-
- Let's take the example from &SetCookies above, with the name and email
- cookies we wish to set. Now, rather than taking up two cookies, we
- can set one cookie named user, which will contain the information
- stored in the name and email cookies. To do this, make you make a call
- like:
-
- print "Content-type: text/html\n";
- &SetCompressedCookies('user','name',$name,'email',$email);
- print "\n";
-
- This sets a cookie named user which contains the cookies name and email.
- In order to uncompress this cookie, you need to use the
- &GetCompressedCookies subroutine explained below. It acts much like
- &GetCookies.
-
- WARNING: It is a good idea not to set the compressed cookie name equal
- to the name of a cookie being stored in the compressed cookie.
- It can mess things up.
-
- &GetCompressedCookies('compressed_cookie_name','cookie_name1',...,'cookie_namen');
-
- This subroutine works in almost the same way as &GetCookies, except that
- it needs the name of the compressed cookie first, followed by the names
- of the cookies you wish to retrieve out of the compressed cookie. If
- this subroutine is called with only the name of the compressed cookie,
- it will retrieve all values and place them in the %Cookies array.
-
- For instance, if we were to take the example used in
- &SetCompressedCookies and we needed to only get the name of the user out
- of the compressed cookie, we would do something like:
-
- &GetCompressedCookies('user','name');
-
- Where 'user' was the name of the cookie we specified to be set when we
- compressed the cookies and 'name' was one of the cookies we compressed
- into 'user'. The value of name can not be retrieved from
- $Cookies{'name'}.
-
- Or if you wished to get every cookie out of the compressed cookie, you
- can simply say:
-
- &GetCompressedCookies('user');
-
- And now $Cookies{'name'} and $Cookies{'email'} are set.
-
- ##############################################################################
-
- CHARACTER TRANSLATION INFORMATION
- =================================
-
- Version 2.1 of the HTTP Cookie Library introduces some simple character
- URL-encoding which eases the use and fixes some common problems with cookies.
- Previously, cookies would often not be set if they included spaces, semi-
- colons, and a few other special characters. There was also the problem found
- if information contained two :: or an & and you tried to compress the cookies,
- because those two characters are used for the compression sequence that HTTP
- Cookie Library uses.
-
- According to Netscape's Persistent Client State HTTP Specification:
-
- "This string is a sequence of characters excluding semi-colon, comma
- and white space. If there is a need to place such data in the name
- or value, some encoding method such as URL style %XX encoding is
- recommended, though no encoding is defined or required."
-
- HTTP Cookie Library does use the URL style %XX (also known as hex) encoding to
- ensure that these characters are not lost and that the cookie is set.
-
- ##############################################################################
-
- ANY EXAMPLES AVAILABLE?
- =======================
-
- ccounter.pl
- -----------
-
- ccounter.pl, an example of how to use some of the features in this
- library comes bundled with the script. Hopefully the docs have been
- written extensively enough and the library commented enough (this is
- the most commented and well-documented script at MSA) that it should
- be fairly easy to figure out.
-
- Scripts Around the World
- ------------------------
-
- You can find real-world implementations of this library listed at MSA
- in the Scripts Around the World section. The HTTP Cookie Library page
- for this can be found at:
-
- http://www.worldwidemart.com/scripts/examples/cookielib.shtml
-
- If you have used the library, please let us know so we can add it!
-
- ##############################################################################
-
- OTHER COOKIE RESOURCES
- ======================
-
- There are many other cookie resources available on the Internet. Below are
- just a few that are the most useful and should help you out. Enjoy.
-
- Netscape Persistent Client State HTTP Cookies Specification
- http://www.netscape.com/newsref/std/cookie_spec.html
- The specifications to which this library conforms. Contains a lot of
- useful information on Cookies in general and how they can be used.
-
- Andy's Netscape HTTP Cookie Info
- http://www.illuminatus.com/cookie.fcgi
- A lot of information on cookies, the security of them, Frequently Asked
- Questions and much more. A LOT of cookie information. :-)
-
- Malcolm's Guide to Persistent Cookies
- http://www.emf.net/~mal/cookiesinfo.html
- This guide to Persistant Cookies explains what cookies are, discusses
- security and privacy issues, gives URLS to more documentation and shows
- some examples of places using cookies.
-
- Javascript Cookie Functions
- http://www.hidaho.com/cookies/cookie.txt
- A library much like this one with different subroutines, only
- implemented in JavaScript.
-
- HTTP State Management Mechanism RFC
- http://portal.research.bell-labs.com/~dmk/cookie-2.36.txt
- Looks very cookie-related. Maybe I should start conforming to this.
-
- ##############################################################################
-
- HISTORY
-
- Version 2.1 - 12/19/96 - Changed the local() scope of global
- variables because they weren't setting at
- the top of the script right.
- - 12/20/96 - Added URL-encoding to the cookies for the
- characters: '%', '+', ':', ',', '=', '&',
- '::', and space. More on this explained
- in the section, 'Character Translation'.
- - &UnCompressCookies changed to
- &GetCompressedCookies, making more sense.
- - 12/23/96 - &SetCookieExpDate fixed to allow a blank
- date.
- Version 2.0 - 11/28/96 - &SetCookieExpDate still not working right,
- and finall fixed.
- - &SetCompressedCookies and &UnCompressCookies
- subroutines added so multiple cookies can be
- set as one cookie and take up less room in
- the cookies.txt file.
- - &PrepareCookie replaced by changing
- &SetCookies to do all of the work. This
- subroutine now actually takes values and
- sets them.
- - Multiple cookied can be set now. A bug
- existed before which wouldn't set all of
- the cookies.
- - Checking now done when setting cookie domain
- so you can know if it will work. Based on
- information in Netscape's Specifications.
- Version 1.1.1 - 07/15/96 - Andy Kington <andyk@teleport.com>
- pointed out that the ExpDate Year should be
- represented as YYYY instead of YY.
- Version 1.1 - 07/14/96 - Added secure option and routines.
- Version 1.0 - 07/14/96 - First Version Released
-
- ##############################################################################
-
- Have fun with this script, but if you can, please, please let me know the URL
- of where it is implemented so I can see my work in action (and add you to the
- list of sites using this script.)
-
- ##############################################################################
- Matt Wright - mattw@worldwidemart.com http://www.worldwidemart.com/scripts/
-